﻿// vcpkg_integrate_test.cpp: 定义应用程序的入口点。
//

#include "test_subscribe.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h>
#include <hiredis/hiredis.h>
#include <event2/event.h>
#include <hiredis/async.h>
#include <hiredis/adapters/libevent.h>
#include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/spdlog.h>
#include <event2/http.h>
#include <event2/buffer.h>
#include "../message/message.h"
#include "../../utils/bytes_utils.h"
#include "../../compositions/Base64/Base64.h"

void messageCallback(redisAsyncContext* c, void* reply, void* privdata) {
    redisReply* r = (redisReply*)reply;
    if (r == NULL) return;
    if (r->type == REDIS_REPLY_ARRAY && r->elements == 3) {
        if (strcmp(r->element[0]->str, "message") == 0) {
            //printf("Received message: %s\n", r->element[2]->str);

            spdlog::info("\n\n----------------------------------------------------------------");
            spdlog::info("Received message: {}   len:{}", r->element[2]->str,r->element[2]->len);
            std::string resReceiveData(r->element[2]->str);
            //base64转换为字节
            std::vector<unsigned char> receiveByteData=Base64::base64Decode(resReceiveData);
            std::string strByteData(receiveByteData.begin(),receiveByteData.end());

            //解包头
            msg::message receiveDataHead;//target head
            receiveDataHead.decode(strByteData, receiveDataHead);
            //const char* ress = res.c_str();
            //解包数据
            std::string body_data;
            memcpy((void*)body_data.c_str(), strByteData.c_str() + sizeof(msg::message), receiveDataHead.body_len);

            spdlog::info("Received message2: head data> version:{} source:{}", receiveDataHead.version, receiveDataHead.source);

            spdlog::info("Received message2: body data:{}   len:{}", body_data.c_str(), receiveDataHead.body_len);

        }
    }
}
void requestHandler(struct evhttp_request* req, void* arg) {
    struct evbuffer* buf = evbuffer_new();
    if (buf == nullptr) {
        std::cerr << "Error creating response buffer" << std::endl;
        return;
    }
    spdlog::info("HTTP message: {}", "Hello, this is a simple HTTP server using libevent");
    evbuffer_add_printf(buf, "Hello, this is a simple HTTP server using libevent\n");
    evhttp_send_reply(req, HTTP_OK, "OK", buf);

    evbuffer_free(buf);
}
int main() {
    
    spdlog::set_level(spdlog::level::debug);
    std::vector<spdlog::sink_ptr> sinks;
    sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_st>());
    sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_st>("logs/basic-log.log", 23, 59));
    auto combined_logger = std::make_shared<spdlog::logger>("logger", begin(sinks), end(sinks));
    //register it if you need to access it globally
    spdlog::register_logger(combined_logger);
    spdlog::set_default_logger(combined_logger);//todo 默认日志不能记录到文件

    //auto rotating_logger = spdlog::rotating_logger_mt("logger", "logs/basic-log.txt", 1024 * 1024 * 100, 3);
    //spdlog::set_default_logger(rotating_logger);//todo 屏幕不能打印

    spdlog::set_pattern(">>>>[%P] %# [thread %t] [%Y-%m-%d %H:%M:%S:%e] %v ***");

#ifdef _WIN32

    /* 初始化 WinSock 库 */
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif // _WIN32


    /* 创建 libevent 事件处理器 */
    struct event_base* base = event_base_new();

    /* 连接 Redis 服务器 */
    redisAsyncContext* c = redisAsyncConnect("127.0.0.1", 6379);
    if (c == NULL || c->err) {
        if (c) {
            printf("Error: %s\n", c->errstr);
            redisAsyncFree(c);
        }
        else {
            printf("Unable to allocate redis context\n");
        }
        return 1;
    }

    /* 设置消息订阅回调函数 */
    redisLibeventAttach(c, base);
    redisAsyncCommand(c, messageCallback, NULL, "SUBSCRIBE channel");
    spdlog::info("..................init redis subscribe success..............");


    struct evhttp* http = evhttp_new(base);
    if (!http) {
        std::cerr << "Error creating HTTP server" << std::endl;
        return -1;
    }

    // 设置监听地址和端口
    if (evhttp_bind_socket(http, "0.0.0.0", 9098) != 0) {
        std::cerr << "Error binding socket" << std::endl;
        return -1;
    }

    // 设置请求处理函数
    evhttp_set_gencb(http, requestHandler, nullptr);

    std::cout << "HTTP server is running on port 9098" << std::endl;


    /* 进入 libevent 事件循环 */
    event_base_dispatch(base);

    /* 释放资源 */
    evhttp_free(http);
    event_base_free(base);
    redisAsyncFree(c);
    WSACleanup();
    return 0;
}
